package config

import (
	"flag"
	"gitverse.ru/synapse/kubelatte/pkg/logs"
	"gitverse.ru/synapse/kubelatte/pkg/util"
	"os"
	"path/filepath"
	"strconv"

	"github.com/jessevdk/go-flags"
	"github.com/pkg/errors"
)

const (
	ConfigsPath          = "CONFIGS_PATH"
	LogsPath             = "LOGS_PATH"
	PodClusterName       = "POD_CLUSTER_NAME"
	LogFileNameInjector  = "LOG_FILE_NAME_INJECTOR"
	ServerKey            = "SERVER_KEY"
	ServerCert           = "SERVER_CERT"
	SertCa               = "SERVER_CA"
	DummyPod             = "DUMMY_POD"
	TLSPort              = "TLS_PORT"
	HTTPPort             = "HTTP_PORT"
	SidecarConfigFile    = "TEMPLATE_FILE"
	MutationConfigFile   = "TRIGGER_FILE"
	ScopeValidation      = "KBLT_VALIDATION"
	EnabledTriggerPrefix = "KBLT_ENABLED_TRIGGER_PREFIX"
	Prefix               = "kblt"
)

// WebhookConfig is the configuration parameters for the sidecar injector
type WebhookConfig struct {
	TLSPort                  int    `long:"port"  required:"false" description:"webhook server port for mutate endpoint"`
	HTTPPort                 int    `long:"http-port" default:"17773" required:"false" description:"webhook server http port for metrics and healthz endpoints"`
	CertFilePath             string `long:"cert-file-path" required:"false" description:"file containing the x509 Certificate for HTTPS"`
	KeyFilePath              string `long:"key-file-path" required:"false" description:"file containing the x509 private key"`
	CaFilePath               string `long:"ca-file-path" required:"false" description:"file containing the CA cert"`
	SidecarConfigFile        string `long:"sidecar-config-file" required:"false" description:"file containing the sidecar container configuration"`
	MutationConfigFile       string `long:"mutation-config-file" required:"false" description:"file containing the mutation configuration"`
	BuildInfoLabels          string `long:"build-info-labels" required:"false" description:"additional build info metric labels"`
	ConfDir                  string `long:"sidecar-mutating-conf-dir" required:"false" description:"if specify add dir to sidecar and mutating configs"`
	LogFile                  string `long:"log-file" required:"false" description:"fiete fluent-bit logs"`
	SanityPodFilePath        string `long:"sanity-pod-file-path" required:"false" description:"if set, sanity pod gets from file, if file not found default sanity pod loaded"`
	AllowDeprecatedTLSConfig bool   `long:"allow-deprecated-tls-config" required:"false" description:"permits use of deprecated TLS configuration (TLS 1.0/1.1, weak ciphers)"`
	EnabledTriggerPrefix     bool   `long:"enabled-trigger-prefix" required:"false" description:"adding a prefix in custom annotations"`
}

// NewWebhookConfig is a constructor for WebhookConfig
func NewWebhookConfig() (*WebhookConfig, error) {
	config, err := parse()
	if err != nil {
		return nil, errors.Errorf("api=NewWebhookConfig, reason=parse, err=%v", err)
	}
	return config, nil
}

// parse the args and environment to fill the ClientConfig
func parse() (*WebhookConfig, error) {
	c := &WebhookConfig{}
	parser := flags.NewParser(c, flags.HelpFlag|flags.PrintErrors|flags.PassDoubleDash|flags.IgnoreUnknown)
	extraArgs, err := parser.Parse()
	if err != nil {
		return nil, errors.Errorf("api=parse, err=%v", err)
	}
	if c.ConfDir == "" {
		c.ConfDir = os.Getenv(ConfigsPath)
	}

	if c.LogFile == "" {
		c.LogFile = filepath.Join(os.Getenv(LogsPath), os.Getenv(LogFileNameInjector))
		logs.LogsFluentPath = c.LogFile
	}
	if c.KeyFilePath == "" {
		c.KeyFilePath = os.Getenv(ServerKey)
	}
	if c.CertFilePath == "" {
		c.CertFilePath = os.Getenv(ServerCert)
	}

	if c.CaFilePath == "" {
		c.CaFilePath = os.Getenv(SertCa)
	}

	if c.SanityPodFilePath == "" {
		c.SanityPodFilePath = os.Getenv(DummyPod)
	}

	if c.SidecarConfigFile == "" {
		c.SidecarConfigFile = os.Getenv(SidecarConfigFile)
	}

	if c.MutationConfigFile == "" {
		c.MutationConfigFile = os.Getenv(MutationConfigFile)
	}
	tlsPort := os.Getenv(TLSPort)
	if tlsPort != "" {
		p, err := strconv.Atoi(tlsPort)
		if err != nil {
			logs.Errorf("port: %s must by int number from 0 to 65535", tlsPort)
		} else {
			c.TLSPort = p
		}
	}

	// Parse any extra args for dependent packages that use "flag" (e.g., logs).
	flag.CommandLine.Parse(extraArgs)
	return c, nil
}

func Load() (*WebhookConfig, error) {

	util.StatusInfo = nil

	webhookConfig, err := NewWebhookConfig()
	if err != nil {
		return nil, err
	}

	var flagsErr *flags.Error
	if errors.As(err, &flagsErr) && errors.Is(flagsErr.Type, flags.ErrHelp) {
		return nil, err
	}

	return webhookConfig, nil
}
